
import threading
import os
from loguru import logger
from django.shortcuts import render
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework.parsers import MultiPartParser, FormParser, JSONParser
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from django.shortcuts import get_object_or_404
from django.http import HttpResponse
from .models import ProjectModel, ProjectVersionModel
from .serializers import (
    ProjectSerializer, ProjectListSerializer, ProjectVersionSerializer,
    FileUploadSerializer, IndexContentUpdateSerializer, VersionRollbackSerializer,
    VersionCreateSerializer, FilePathSerializer
)
from apps.middleware import CustomUserPermission, CustomUserAuthentication


# Create your views here.


_tag = "Project"


class ProjectViewSet(viewsets.ModelViewSet):
    """项目管理视图集"""
    queryset = ProjectModel.objects.all()
    serializer_class = ProjectSerializer
    permission_classes = [CustomUserPermission]
    authentication_classes = [CustomUserAuthentication]
    
    def get_queryset(self):
        """用户只能访问自己创建的项目"""
        # 🔧 处理Swagger文档生成时的匿名用户问题
        if getattr(self, 'swagger_fake_view', False):
            return ProjectModel.objects.none()
        
        if not self.request.user.is_authenticated:
            return ProjectModel.objects.none()
            
        if self.request.user.is_superuser:
            return ProjectModel.objects.all()
        return ProjectModel.objects.filter(creator=self.request.user)
    
    def get_serializer_class(self):
        """根据不同的action选择不同的序列化器"""
        action_serializers = {
            'list': ProjectListSerializer,
            'upload_files': FileUploadSerializer,  
            'update_index': IndexContentUpdateSerializer,
            'rollback_to_version': VersionRollbackSerializer,
            'create_version': VersionCreateSerializer,
            'delete_file': FilePathSerializer,
        }
        return action_serializers.get(self.action, ProjectSerializer)
    
    def perform_create(self, serializer):
        """创建项目时设置创建者"""
        serializer.save(creator=self.request.user)
    
    @action(detail=True, methods=['get'])
    def versions(self, request, pk=None):
        """获取项目的所有版本"""
        project = self.get_object()
        versions = project.versions.all()
        serializer = ProjectVersionSerializer(versions, many=True)
        return Response(serializer.data)
    
    @action(detail=True, methods=['post'])
    def create_version(self, request, pk=None):
        """创建新版本"""
        project = self.get_object()
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        content = serializer.validated_data['content']
        
        # 创建新版本
        version = ProjectVersionModel.objects.create(
            project=project,
            version=project.version_count + 1,
            content=content,
            creator=request.user
        )
        
        # 更新项目的当前内容和版本计数
        project.current_content = content
        project.version_count += 1
        project.save()
        
        serializer = ProjectVersionSerializer(version)
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    
    @action(detail=True, methods=['post'])
    def rollback_to_version(self, request, pk=None):
        """回滚到指定版本"""
        project = self.get_object()
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        version_number = serializer.validated_data['version']
        
        version = get_object_or_404(
            ProjectVersionModel, 
            project=project, 
            version=version_number
        )
        
        # 将指定版本的内容设为当前内容
        project.current_content = version.content
        project.save()
        
        return Response({
            'message': f'已回滚到版本 {version_number}',
            'current_content': project.current_content
        })
    
    @action(detail=True, methods=['get'])
    def download(self, request, pk=None):
        """下载项目的markdown文件"""
        project = self.get_object()
        
        response = HttpResponse(
            project.current_content or '', 
            content_type='text/markdown'
        )
        response['Content-Disposition'] = f'attachment; filename="{project.name}.md"'
        return response
    
    @action(detail=True, methods=['get'])
    def directory_tree(self, request, pk=None):
        """获取项目目录树"""
        project = self.get_object()
        tree = project.get_directory_tree()
        return Response({
            'tree': tree,
            'project_path': project.project_path
        })
    
    @action(detail=True, methods=['get'])
    def background(self, request, pk=None):
        """获取项目背景信息"""
        project = self.get_object()
        background_content = project.get_background_content()
        return Response({
            'content': background_content,
            'file_path': project.get_background_md_path()
        })
    
    @action(detail=True, methods=['get'])
    def index_content(self, request, pk=None):
        """获取项目主要内容（index.md）"""
        project = self.get_object()
        index_content = project.get_index_md_content()
        return Response({
            'content': index_content,
            'file_path': project.get_index_md_path(),
            'has_content': bool(index_content.strip())
        })
    
    @action(detail=True, methods=['post'])
    def update_index(self, request, pk=None):
        """手动更新项目主要内容（index.md）"""
        project = self.get_object()
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        content = serializer.validated_data['content']
        
        # 写入index.md
        index_path = project.write_index_md(content)
        
        # 更新background.md
        project.update_background_md()
        
        return Response({
            'content': content,
            'file_path': index_path,
            'message': '项目内容已更新'
        })
    
    @action(detail=True, methods=['post'])
    def update_background(self, request, pk=None):
        """更新项目背景信息"""
        project = self.get_object()
        content = project.update_background_md()
        return Response({
            'content': content,
            'message': '背景信息已更新'
        })
    
    @swagger_auto_schema(
        method='post',
        operation_description="上传文件到已存在的项目 - 自动解析文件并生成AI背景",
        **FileUploadSerializer.schema()
    )
    @action(detail=True, methods=['post'], parser_classes=[MultiPartParser, FormParser])
    def upload_files(self, request, pk=None):
        """
        📁 文件上传与智能解析
        
        流程：
        1. 创建项目（仅基本信息）
        2. 使用此接口上传文件
        3. 系统自动解析文件并生成AI背景
        """
        project = self.get_object()
        
        # 手动验证文件
        if 'files' not in request.FILES:
            return Response(
                {'error': '没有上传文件'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        uploaded_files = request.FILES.getlist('files')
        if not uploaded_files:
            return Response(
                {'error': '至少需要上传一个文件'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 文件大小验证
        max_size = 50 * 1024 * 1024  # 50MB
        for file in uploaded_files:
            if file.size > max_size:
                return Response(
                    {'error': f'文件 {file.name} 超过大小限制 (50MB)'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
        
        print(f"🚀 开始为项目 '{project.name}' (ID: {project.id}) 处理 {len(uploaded_files)} 个文件")
        file_paths = []
        
        # 处理每个上传的文件
        for file in uploaded_files:
            try:
                if file.name.endswith('.zip'):
                    # 处理zip文件
                    print(f"📦 解压ZIP文件: {file.name}")
                    self._extract_zip_file(project, file)
                    file_paths.append(f"解压: {file.name}")
                elif file.name.endswith('.md'):
                    # markdown文件
                    print(f"📝 处理Markdown文件: {file.name}")
                    path = project.add_uploaded_file(file, 'docs')
                    file_paths.append(path)
                elif self._is_image_file(file.name):
                    # 图片文件
                    print(f"🖼️ 处理图片文件: {file.name}")
                    path = project.add_uploaded_file(file, 'images')
                    file_paths.append(path)
                else:
                    # 其他文件
                    print(f"📄 处理其他文件: {file.name}")
                    path = project.add_uploaded_file(file, 'assets')
                    file_paths.append(path)
            except Exception as e:
                print(f"❌ 处理文件 {file.name} 时出错: {str(e)}")
                return Response(
                    {'error': f'处理文件 {file.name} 时出错: {str(e)}'}, 
                    status=status.HTTP_500_INTERNAL_SERVER_ERROR
                )
        
        # 🤖 自动生成AI智能背景
        print(f"🤖 开始AI智能分析项目内容...")
        try:
            project.generate_ai_background_md()
            background_status = "✅ AI智能背景生成完成"
            print(f"✅ 项目 '{project.name}' 的AI背景分析完成")
        except Exception as e:
            # AI生成失败时回退到简单背景
            project.update_background_md()
            background_status = f"⚠️ 使用简单背景（AI生成失败: {str(e)}）"
            print(f"⚠️ AI背景生成失败，使用简单背景: {str(e)}")
        
        return Response({
            'message': f'🎉 成功上传 {len(file_paths)} 个文件到项目 "{project.name}"',
            'uploaded_files': file_paths,
            'directory_tree': project.get_directory_tree(),
            'background_status': background_status,
            'project_id': str(project.id),
            'project_name': project.name
        })
    
    @action(detail=True, methods=['delete'])
    def delete_file(self, request, pk=None):
        """删除项目中的文件"""
        project = self.get_object()
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        file_path = serializer.validated_data['file_path']
        
        import os
        full_path = os.path.join(project.project_path, file_path)
        
        if not os.path.exists(full_path):
            return Response(
                {'error': '文件不存在'}, 
                status=status.HTTP_404_NOT_FOUND
            )
        
        # 安全检查：确保文件在项目目录内
        if not full_path.startswith(project.project_path):
            return Response(
                {'error': '无效的文件路径'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        try:
            os.remove(full_path)
            # 更新background.md
            project.update_background_md()
            
            return Response({
                'message': f'文件 {file_path} 已删除',
                'directory_tree': project.get_directory_tree()
            })
        except Exception as e:
            return Response(
                {'error': f'删除文件时出错: {str(e)}'}, 
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    @action(detail=True, methods=['get'])
    def download_file(self, request, pk=None):
        """下载项目中的特定文件"""
        project = self.get_object()
        file_path = request.query_params.get('file_path')
        
        if not file_path:
            return Response(
                {'error': '请提供文件路径'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        import os
        import mimetypes
        full_path = os.path.join(project.project_path, file_path)
        
        if not os.path.exists(full_path):
            return Response(
                {'error': '文件不存在'}, 
                status=status.HTTP_404_NOT_FOUND
            )
        
        # 安全检查
        if not full_path.startswith(project.project_path):
            return Response(
                {'error': '无效的文件路径'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        try:
            with open(full_path, 'rb') as f:
                content = f.read()
            
            # 获取文件的MIME类型
            content_type, _ = mimetypes.guess_type(full_path)
            if not content_type:
                content_type = 'application/octet-stream'
            
            response = HttpResponse(content, content_type=content_type)
            response['Content-Disposition'] = f'attachment; filename="{os.path.basename(file_path)}"'
            return response
            
        except Exception as e:
            return Response(
                {'error': f'读取文件时出错: {str(e)}'}, 
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    def _extract_zip_file(self, project, zip_file):
        """解压zip文件到项目目录"""
        import zipfile
        import tempfile
        import os
        from pathlib import Path
        
        with tempfile.TemporaryDirectory() as temp_dir:
            temp_zip_path = os.path.join(temp_dir, zip_file.name)
            
            # 保存zip文件到临时目录
            with open(temp_zip_path, 'wb+') as destination:
                for chunk in zip_file.chunks():
                    destination.write(chunk)
            
            # 解压文件
            with zipfile.ZipFile(temp_zip_path, 'r') as zip_ref:
                extract_path = os.path.join(temp_dir, 'extracted')
                zip_ref.extractall(extract_path)
                
                # 将解压的文件复制到项目目录
                self._copy_extracted_files(project, extract_path)
    
    def _copy_extracted_files(self, project, extract_path):
        """将解压的文件复制到项目目录"""
        import shutil
        import os
        from pathlib import Path
        
        for root, dirs, files in os.walk(extract_path):
            for file in files:
                source_path = os.path.join(root, file)
                
                # 确定目标子目录
                if file.endswith('.md'):
                    target_subdir = 'docs'
                elif self._is_image_file(file):
                    target_subdir = 'images'
                else:
                    target_subdir = 'assets'
                
                # 构建目标路径，保持目录结构
                relative_path = os.path.relpath(source_path, extract_path)
                target_dir = os.path.join(project.project_path, target_subdir)
                target_path = os.path.join(target_dir, os.path.basename(file))
                
                # 如果文件名重复，添加序号
                counter = 1
                base_name, ext = os.path.splitext(os.path.basename(file))
                while os.path.exists(target_path):
                    new_name = f"{base_name}_{counter}{ext}"
                    target_path = os.path.join(target_dir, new_name)
                    counter += 1
                
                # 确保目标目录存在
                Path(target_dir).mkdir(parents=True, exist_ok=True)
                
                # 复制文件
                shutil.copy2(source_path, target_path)
    
    def _is_image_file(self, filename):
        """检查是否为图片文件"""
        image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg', '.webp']
        return any(filename.lower().endswith(ext) for ext in image_extensions)

